package com.xtianzhuang.www.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.xtianzhuang.www.dao.TdAccountMapper;
import com.xtianzhuang.www.dao.TfUserDailyBalanceMapper;
import com.xtianzhuang.www.dao.TmUUserAccountMapper;
import com.xtianzhuang.www.dao.VUserAccountMapper;
import com.xtianzhuang.www.dao.VUserDailyBalanceMapper;
import com.xtianzhuang.www.dao.others.TfUserDailyBalanceOtherMapper;
import com.xtianzhuang.www.entity.TdAccount;
import com.xtianzhuang.www.entity.TfUserDailyBalance;
import com.xtianzhuang.www.entity.TmUUserAccount;
import com.xtianzhuang.www.entity.VUserAccount;
import com.xtianzhuang.www.entity.VUserAccountExample;
import com.xtianzhuang.www.entity.VUserDailyBalance;
import com.xtianzhuang.www.entity.VUserDailyBalanceExample;
import com.xtianzhuang.www.entity.constants.AccountBigTypeConstants;
import com.xtianzhuang.www.entity.constants.IsDeletedConstants;
import com.xtianzhuang.www.entity.constants.PayTypeConstants;
import com.xtianzhuang.www.entity.request.DeleteBalanceRequest;
import com.xtianzhuang.www.entity.request.QueryDailyBalanceRequest;
import com.xtianzhuang.www.entity.request.SaveAccountRequest;
import com.xtianzhuang.www.entity.request.SaveDailyBalanceRequest;
import com.xtianzhuang.www.entity.response.DailyBalance;
import com.xtianzhuang.www.service.FinanceService;
import com.xtianzhuang.www.service.base.BaseServiceBiz;

@Service("financeServiceBiz")
@Transactional(rollbackFor = Exception.class)
public class FinanceServiceBiz extends BaseServiceBiz implements FinanceService {
	@Autowired
	private TdAccountMapper tdAccountMapper;
	@Autowired
	private TmUUserAccountMapper tmUUserAccountMapper;
	@Autowired
	private TfUserDailyBalanceMapper tfUserDailyBalanceMapper;
	@Autowired
	private TfUserDailyBalanceOtherMapper tfUserDailyBalanceOtherMapper;
	@Autowired
	private VUserAccountMapper vUserAccountMapper;
	@Autowired
	private VUserDailyBalanceMapper vUserDailyBalanceMapper;
	@Override
	public void saveAccount(SaveAccountRequest request) throws Exception {
		// TODO Auto-generated method stub
		Integer accountId = addTdAccount(request);
		addTmUUserAccount(accountId);

	}

	public Integer addTdAccount(SaveAccountRequest request) throws Exception {
		TdAccount tdAccount = new TdAccount();
		tdAccount.setAccountName(request.getAccountName());
		tdAccount.setAccountType(request.getAccountType());
		tdAccount.setAssets(request.getAssets());
		tdAccount.setAccountBigType(request.getAccountBigType());
		tdAccount.setAccountDivide(request.getAccountDivide());
		tdAccount.setRemark(request.getRemark());
		tdAccount.setCreateStaffId(subject.getPrincipal().getUserName());
		tdAccount.setCreateTime(new Date());
		tdAccountMapper.insert(tdAccount);
		return tdAccount.getAccountId();

	}

	public void addTmUUserAccount(Integer acountId) throws Exception {
		TmUUserAccount tmUUserAccount = new TmUUserAccount();
		tmUUserAccount.setAccountId(acountId);
		tmUUserAccount.setIsDeleted(IsDeletedConstants.IN_USE);
		tmUUserAccount.setUserId(subject.getPrincipal().getUserId());
		tmUUserAccount.setCreateTime(new Date());
		tmUUserAccount.setCreateStaffId(subject.getPrincipal().getUserName());
		tmUUserAccountMapper.insert(tmUUserAccount);
	}

	@Override
	public void saveUserDailyBalancePay(SaveDailyBalanceRequest request) throws Exception {
		// TODO Auto-generated method stub
		// 明细
		request.setPayType(PayTypeConstants.PAY);
		addTfUserDailyBalance(request);
		// 对应账户扣钱 债权为减 负债为加
		updateTdAccountReduce(request.getAccountA(), request.getMoney());
	}

	@Override
	public void saveUserDailyBalanceIncome(SaveDailyBalanceRequest request) throws Exception {
		// TODO Auto-generated method stub
		// 明细
		request.setPayType(PayTypeConstants.INCOME);
		addTfUserDailyBalance(request);
		// 对应账户加钱 债权为加 负债为减
		updateTdAccountIncrease(request.getAccountA(), request.getMoney());
	}

	@Override
	public void saveUserDailyBalanceTransfer(SaveDailyBalanceRequest request) throws Exception {
		// TODO Auto-generated method stub
		// 明细
		request.setPayType(PayTypeConstants.TRANSFER);
		addTfUserDailyBalance(request);
		// 对应账户B加钱,A减钱 债权为加 负债为减
		updateTdAccountReduce(request.getAccountA(), request.getMoney());
		updateTdAccountIncrease(request.getAccountB(), request.getMoney());

	}

	public void updateTdAccountReduce(Integer accountId, BigDecimal money) throws Exception {
		TdAccount tdAccount = tdAccountMapper.selectByPrimaryKey(accountId);
		if (tdAccount != null) {
			if (tdAccount.getAccountBigType().equals("1")) {
				if (tdAccount.getAssets().compareTo(money) < 0) {
					throw new Exception("余额不足");
				} else {
					tdAccount.setAssets(tdAccount.getAssets().subtract(money));
					tdAccount.setUpdateTime(new Date());
					tdAccount.setUpdateStaffId(subject.getPrincipal().getUserName());
				}
				tdAccountMapper.updateByPrimaryKey(tdAccount);
			} else if (tdAccount.getAccountBigType().equals("-1")) {
				tdAccount.setAssets(tdAccount.getAssets().add(money));
				tdAccount.setUpdateTime(new Date());
				tdAccount.setUpdateStaffId(subject.getPrincipal().getUserName());
				tdAccountMapper.updateByPrimaryKey(tdAccount);
			}
		}
	}

	public void updateTdAccountIncrease(Integer accountId, BigDecimal money) throws Exception {
		TdAccount tdAccount = tdAccountMapper.selectByPrimaryKey(accountId);
		if (tdAccount != null) {
			if (tdAccount.getAccountBigType().equals("1")) {
				tdAccount.setAssets(tdAccount.getAssets().add(money));
				tdAccount.setUpdateTime(new Date());
				tdAccount.setUpdateStaffId(subject.getPrincipal().getUserName());
				tdAccountMapper.updateByPrimaryKey(tdAccount);
			} else if (tdAccount.getAccountBigType().equals("-1")) {
				if (tdAccount.getAssets().compareTo(money) < 0) {
					throw new Exception("负债账户不能为负");
				} else {
					tdAccount.setAssets(tdAccount.getAssets().subtract(money));
					tdAccount.setUpdateTime(new Date());
					tdAccount.setUpdateStaffId(subject.getPrincipal().getUserName());
					tdAccountMapper.updateByPrimaryKey(tdAccount);
				}
			}
		}
	}


	public void addTfUserDailyBalance(SaveDailyBalanceRequest request) throws Exception {
		// TODO Auto-generated method stub
		TfUserDailyBalance tfUserDailyBalance = new TfUserDailyBalance();
		tfUserDailyBalance.setIsDeleted(IsDeletedConstants.IN_USE);
		tfUserDailyBalance.setBalanceType(request.getBalanceType());
		tfUserDailyBalance.setCreateStaffId(subject.getPrincipal().getUserName());
		tfUserDailyBalance.setDate(request.getDate());
		tfUserDailyBalance.setMoney(request.getMoney());
		tfUserDailyBalance.setPayType(request.getPayType());
		tfUserDailyBalance.setRemark(request.getRemark());
		tfUserDailyBalance.setAccountA(request.getAccountA());
		tfUserDailyBalance.setAccountB(request.getAccountB());
		tfUserDailyBalance.setCreateTime(new Date());
		tfUserDailyBalance.setUserId(subject.getPrincipal().getUserId());
		tfUserDailyBalanceMapper.insert(tfUserDailyBalance);
	}

	@Override
	public List<VUserAccount> getBondAccount() {
		// TODO Auto-generated method stub
		VUserAccountExample example = new VUserAccountExample();
		example.or().andAccountBigTypeEqualTo(AccountBigTypeConstants.DEBT_ACCOUNT)
				.andUserIdEqualTo(subject.getPrincipal().getUserId());
		return vUserAccountMapper.selectByExample(example);
	}

	@Override
	public List<VUserAccount> getliabilityAccounts() {
		// TODO Auto-generated method stub
		VUserAccountExample example = new VUserAccountExample();
		example.or().andAccountBigTypeEqualTo(AccountBigTypeConstants.LIABILITY_ACCOUNT)
				.andUserIdEqualTo(subject.getPrincipal().getUserId());
		return vUserAccountMapper.selectByExample(example);
	}

	@Override
	public List<VUserDailyBalance> queryDailyBalance(QueryDailyBalanceRequest request) {
		// TODO Auto-generated method stub
		VUserDailyBalanceExample example = new VUserDailyBalanceExample();
		VUserDailyBalanceExample.Criteria criteria = example.createCriteria();
		String date = "%";
		if (StringUtils.isNotBlank(request.getDate())) {
			criteria.andDateEqualTo(request.getDate());
		} else if (StringUtils.isNotEmpty(request.getYearType()) || StringUtils.isNotEmpty(request.getMonthType())) {
			if (StringUtils.isNotEmpty(request.getYearType())) {
				date += request.getYearType() + "%";
			}
			if (StringUtils.isNotEmpty(request.getMonthType())) {
				date += "-" + request.getMonthType() + "-%";
			}
			criteria.andDateLike(date);
		}
		criteria.andUserIdEqualTo(subject.getPrincipal().getUserId());
		if (StringUtils.isNotEmpty(request.getPayType())) {
			criteria.andPayTypeEqualTo(request.getPayType());
		}
		if (StringUtils.isNotEmpty(request.getBalanceType())) {
			criteria.andBalanceTypeEqualTo(request.getBalanceType());
		}
		example.setOffset(request.getOffset());
		example.setLimit(request.getLimit());
		example.setOrderByClause("id desc");
		return vUserDailyBalanceMapper.selectByExample(example);
	}

	@Override
	public long queryDailyBalanceCount(QueryDailyBalanceRequest request) {
		VUserDailyBalanceExample example = new VUserDailyBalanceExample();
		VUserDailyBalanceExample.Criteria criteria = example.createCriteria();
		String date = "%";
		if (StringUtils.isNotBlank(request.getDate())) {
			criteria.andDateEqualTo(request.getDate());
		} else if (StringUtils.isNotEmpty(request.getYearType()) || StringUtils.isNotEmpty(request.getMonthType())) {
			if (StringUtils.isNotEmpty(request.getYearType())) {
				date += request.getYearType() + "%";
			}
			if (StringUtils.isNotEmpty(request.getMonthType())) {
				date += "-" + request.getMonthType() + "-%";
			}
			criteria.andDateLike(date);
		}
		criteria.andUserIdEqualTo(subject.getPrincipal().getUserId());
		if (StringUtils.isNotEmpty(request.getPayType())) {
			criteria.andPayTypeEqualTo(request.getPayType());
		}
		if (StringUtils.isNotEmpty(request.getBalanceType())) {
			criteria.andBalanceTypeEqualTo(request.getBalanceType());
		}
		return vUserDailyBalanceMapper.countByExample(example);
	}


	@Override
	public void deleteDailyBalance(DeleteBalanceRequest request) throws Exception {
		// TODO Auto-generated method stub
		deleteDailyBalance(request.getId());
		if (request.getPayType().equals(PayTypeConstants.PAY)) {
			// 支出
			updateTdAccountIncrease(request.getAccountA(), request.getMoney());
		} else if (request.getPayType().equals(PayTypeConstants.INCOME)) {
			// 收入
			updateTdAccountReduce(request.getAccountA(), request.getMoney());
		} else if (request.getPayType().equals(PayTypeConstants.TRANSFER)) {
			// 转账
			updateTdAccountIncrease(request.getAccountA(), request.getMoney());
			updateTdAccountReduce(request.getAccountB(), request.getMoney());
		}
	}

	public void deleteDailyBalance(Integer id) {
		TfUserDailyBalance record = new TfUserDailyBalance();
		record.setId(id);
		record.setIsDeleted(IsDeletedConstants.DELETED);
		tfUserDailyBalanceMapper.updateByPrimaryKeySelective(record);
	}

	@Override
	public List<DailyBalance> getDailyBalanceByMonth() {
		// TODO Auto-generated method stub
		SimpleDateFormat sdfDateFormat = new SimpleDateFormat("yyyy-MM");
		String month = sdfDateFormat.format(new Date());
		return tfUserDailyBalanceOtherMapper.getDailyBalanceByMonth(subject.getPrincipal().getUserId(),
				PayTypeConstants.PAY, month);
	}

	@Override
	public List<DailyBalance> getDailyBalanceByMonth(String date) {
		// TODO Auto-generated method stub
		return tfUserDailyBalanceOtherMapper.getDailyBalanceByMonth(subject.getPrincipal().getUserId(),
				PayTypeConstants.PAY, date);
	}

	@Override
	public List<DailyBalance> getDailyIncomeByMonth() {
		// TODO Auto-generated method stub
		SimpleDateFormat sdfDateFormat = new SimpleDateFormat("yyyy-MM");
		String month = sdfDateFormat.format(new Date());
		return tfUserDailyBalanceOtherMapper.getDailyBalanceByMonth(subject.getPrincipal().getUserId(),
				PayTypeConstants.INCOME, month);
	}

	@Override
	public List<DailyBalance> getDailyIncomeByMonth(String date) {
		// TODO Auto-generated method stub
		return tfUserDailyBalanceOtherMapper.getDailyBalanceByMonth(subject.getPrincipal().getUserId(),
				PayTypeConstants.INCOME, date);
	}

	@Override
	public String getDailyBalanceTotalByMonth(String date, String type) {
		// TODO Auto-generated method stub
		if (StringUtils.isEmpty(date)) {
			SimpleDateFormat sdfDateFormat = new SimpleDateFormat("yyyy-MM");
			date = sdfDateFormat.format(new Date());
		}
		return tfUserDailyBalanceOtherMapper.getDailyBalanceTotalByMonth(subject.getPrincipal().getUserId(), type,
				date);

	}

}
